home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-25 | 6.6 KB | 304 lines | [TEXT/CWIE] |
- //
- // This code sample demonstrates how to send an AppleEvent to Finder to induce
- // Finder to unmount a volume. IF FINDER or AT EASE IS RUNNING, this is the only
- // reliable way to perform this task. Otherwise, Finder may have files open on
- // the volume which prevent UnmountVol from succeeding.
- //
- // Of course, if some other application has files open on the volume,
- // UnmountVol will fail anyway, but that's a legitimate error condition.
- //
- // Note this sample decides which volumes to unmount by examining their file
- // system ID. Presently, running this sample will unmount all AppleShare volumes.
- //
- // Complaints and kudos to:
- //
- // Pete Gontier
- // Apple Macintosh Developer Technical Support
- // <gurgle@apple.com>
- //
-
- #define OLDROUTINELOCATIONS 0
- #define OLDROUTINENAMES 0
- #define SystemSevenOrLater 1
-
- #ifndef __AEREGISTRY__
- # include <AERegistry.h>
- #endif
-
- #ifndef __APPLEEVENTS__
- # include <AppleEvents.h>
- #endif
-
- #ifndef __FILES__
- # include <Files.h>
- #endif
-
- #ifndef __ALIASES__
- # include <Aliases.h>
- #endif
-
- #ifndef __LOWMEM__
- # include <LowMem.h>
- #endif
-
- enum
- {
- kFileSystemID_AppleShare = 1,
- kFileSystemID_NetWareFileAccess = 0x1BAD
- };
-
- enum
- {
- kCreatorCode_Finder = 'MACS',
- kCreatorCode_AtEase = 'mfdr'
- };
-
- static pascal OSErr BuildAppleEvent (const HVolumeParam *hvpp, AppleEvent *event)
- {
- OSErr err = noErr;
-
- FSSpecPtr fssP = (FSSpecPtr) NewPtr (sizeof (*fssP));
- if (!(err = MemError ( )))
- {
- if (!(err = FSMakeFSSpec (hvpp->ioVRefNum, fsRtParID, hvpp->ioNamePtr, fssP)))
- {
- AliasHandle aliasH;
-
- if (!(err = NewAlias (nil, fssP, &aliasH)))
- {
- HLockHi ((Handle) aliasH);
- if (!(err = MemError ( )))
- {
- Size size = GetHandleSize ((Handle) aliasH);
- if (!(err = MemError ( )))
- {
- if (!(err = AEPutParamPtr (event,keyDirectObject,typeAlias,*aliasH,size)))
- {
- AEDescList aeDescList;
-
- if (!(err = AECreateList (nil,0,false,&aeDescList)))
- {
- if (!(err = AEPutPtr (&aeDescList,1,typeAlias,*aliasH,size)))
- err = AEPutParamDesc (event,keySelection,&aeDescList);
-
- AEDisposeDesc (&aeDescList);
- }
- }
- }
- }
- DisposeHandle ((Handle) aliasH);
- if (!err) err = MemError ( );
- }
- }
- DisposePtr ((Ptr) fssP);
- if (!err) err = MemError ( );
- }
-
- return err;
- }
-
- static pascal OSErr GetCreatorOfFinderLikeProcess (OSType *processSignature)
- {
- OSErr err = noErr;
-
- ProcessSerialNumber psn = { kNoProcess, kNoProcess };
- ProcessInfoRec pir = { sizeof (pir), nil };
-
- *processSignature = 0;
-
- pir.processAppSpec = nil;
-
- for (;;)
- {
- err = GetNextProcess (&psn);
- if (err)
- {
- if (err == procNotFound) err = noErr;
- break;
- }
-
- err = GetProcessInformation (&psn,&pir);
- if (err) break;
-
- if (pir.processSignature == kCreatorCode_Finder || pir.processSignature == kCreatorCode_AtEase)
- {
- *processSignature = pir.processSignature;
- break;
- }
- }
-
- return err;
- }
-
- static pascal OSErr UnmountAndEject (short vRefNum)
- {
- //
- // Mostly stolen from MoreFiles 1.3.1, but tweaked a little bit for
- // low stack usage, new headers, etc.
- //
-
- OSErr error = noErr;
-
- HParmBlkPtr hpbp = (HParmBlkPtr) NewPtr (sizeof (*hpbp));
- if (!(error = MemError ( )))
- {
- short driveNum;
- Boolean ejected, wantsEject;
- DrvQElPtr drvQElem;
-
- hpbp->volumeParam.ioVRefNum = vRefNum;
- hpbp->volumeParam.ioNamePtr = NULL;
- hpbp->volumeParam.ioVolIndex = 0; // use ioVRefNum only
-
- error = PBHGetVInfoSync(hpbp);
- if ( error == noErr )
- {
- if ( hpbp->volumeParam.ioVDrvInfo != 0 )
- {
- /* the volume is online and not ejected */
- ejected = false;
-
- /* Get the drive number */
- driveNum = hpbp->volumeParam.ioVDrvInfo;
- }
- else
- {
- /* the volume is ejected or offline */
-
- /* Is it ejected? */
- ejected = hpbp->volumeParam.ioVDRefNum > 0;
-
- if ( ejected )
- {
- /* If ejected, the drive number is ioVDRefNum */
- driveNum = hpbp->volumeParam.ioVDRefNum;
- }
- else
- {
- /* If offline, the drive number is the negative of ioVDRefNum */
- driveNum = (short)-(hpbp->volumeParam.ioVDRefNum);
- }
- }
-
- /* find the drive queue element */
- drvQElem = (DrvQElPtr)(LMGetDrvQHdr ( )->qHead);
- while ( (drvQElem != NULL) && (drvQElem->dQDrive != driveNum) )
- {
- drvQElem = (DrvQElPtr)drvQElem->qLink;
- }
-
- if ( drvQElem != NULL )
- {
- /* does the drive want an eject call */
- wantsEject = (*((Ptr)((Ptr)drvQElem - 3)) != 8);
- }
- else
- {
- /* didn't find the drive!! */
- wantsEject = false;
- }
-
- /* unmount the volume */
- hpbp->volumeParam.ioNamePtr = NULL;
- /* ioVRefNum is already filled in from PBHGetVInfo */
- error = PBUnmountVol((ParmBlkPtr) hpbp);
- if ( error == noErr )
- {
- if ( wantsEject && !ejected )
- {
- /* eject the media from the drive if needed */
- hpbp->volumeParam.ioVRefNum = driveNum;
- error = PBEject((ParmBlkPtr) hpbp);
- }
- }
- }
-
- DisposePtr ((Ptr) hpbp);
- if (!error) error = MemError ( );
- }
-
- return ( error );
- }
-
- static pascal OSErr PutAwayOneVolume (const HVolumeParam *hvpp, OSType finderLikeProcess)
- {
- OSErr err = noErr;
-
- if (!finderLikeProcess)
- err = UnmountAndEject (hvpp->ioVRefNum);
- else
- {
- AEAddressDesc address;
-
- if (!(err = AECreateDesc (typeApplSignature, &finderLikeProcess, sizeof (finderLikeProcess), &address)))
- {
- AppleEvent event;
-
- if (!(err = AECreateAppleEvent (kAEFinderEvents,kAEPutAwaySelection,&address,kAutoGenerateReturnID,kAnyTransactionID,&event)))
- {
- if (!(err = BuildAppleEvent (hvpp, &event)))
- {
- AppleEvent reply;
-
- err = AESend (&event,&reply,kAENoReply,kAENormalPriority,kAEDefaultTimeout,nil,nil);
- }
-
- AEDisposeDesc (&event);
- }
-
- AEDisposeDesc (&address);
- }
- }
-
- return err;
- }
-
- static pascal OSErr PutAwayVolumes (short ioVFSID)
- {
- OSErr err = noErr;
-
- OSType finderLikeProcess;
-
- if (!(err = GetCreatorOfFinderLikeProcess (&finderLikeProcess)))
- {
- HParmBlkPtr hpbp = (HParmBlkPtr) NewPtr (sizeof (*hpbp));
- if (!(err = MemError ( )))
- {
- Str27 volumeName;
-
- hpbp->volumeParam.ioNamePtr = volumeName;
- hpbp->volumeParam.ioVolIndex = 1;
-
- for (;;)
- {
- err = PBHGetVInfoSync (hpbp);
- if (err)
- {
- if (err == nsvErr) err = noErr;
- break;
- }
-
- if (hpbp->volumeParam.ioVFSID == ioVFSID)
- {
- err = PutAwayOneVolume (&(hpbp->volumeParam), finderLikeProcess);
- if (err) break;
- }
-
- hpbp->volumeParam.ioVolIndex += 1;
- }
-
- DisposePtr ((Ptr) hpbp);
- if (!err) err = MemError ( );
- }
- }
-
- return err;
- }
-
- void main (void)
- {
- MaxApplZone ( );
- InitGraf (&(qd.thePort)); // AppleEvent Manager needs Random
- (void) PutAwayVolumes (kFileSystemID_AppleShare);
- }
-